package ru.apertum.qsystem.server.controller;

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import ru.apertum.qsystem.SuiteListenerForDb;
import ru.apertum.qsystem.common.cmd.AJsonRPC20;
import ru.apertum.qsystem.common.cmd.CmdParams;
import ru.apertum.qsystem.common.cmd.RpcBanList;
import ru.apertum.qsystem.common.cmd.RpcGetAllServices;
import ru.apertum.qsystem.common.cmd.RpcGetGridOfWeek;
import ru.apertum.qsystem.common.cmd.RpcGetInt;
import ru.apertum.qsystem.common.cmd.RpcGetServiceState;
import ru.apertum.qsystem.common.model.QCustomer;
import ru.apertum.qsystem.server.ServerProps;
import ru.apertum.qsystem.server.model.QServiceTree;

import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

@Listeners({SuiteListenerForDb.class})
public class ExecuterTest {

    CmdParams cmdParams;

    @BeforeMethod
    public void setUp() {
        cmdParams = new CmdParams();
    }

    @Test
    public void testGetInstance() {
        AJsonRPC20 rpc20 = Executer.getInstance().getServicesTask.process(cmdParams, "localhost", new byte[]{127, 0, 0, 1});
        assertNotNull(rpc20);
        assertTrue(rpc20 instanceof RpcGetAllServices);
        RpcGetAllServices allServices = (RpcGetAllServices) rpc20;
        assertEquals(allServices.getResult().getRoot().getName(), "Root of services");
        assertTrue(allServices.getResult().getRoot().getChildren().size() > 0);
    }

    @Test
    public void testAboutTask() {
        // услуга всегда доступна по расписанию.
        cmdParams.serviceId = QServiceTree.getInstance().getById(1540578278210L).getId();
        AJsonRPC20 rpc20 = Executer.getInstance().aboutTask.process(cmdParams, "localhost", new byte[]{127, 0, 0, 1});
        assertNotNull(rpc20);
        assertTrue(rpc20 instanceof RpcGetServiceState);
        RpcGetServiceState serviceState = (RpcGetServiceState) rpc20;
        assertEquals(serviceState.getResult().getLenghtLine(), 0);
        assertEquals(serviceState.getResult().getCode(), 0);

        // услгуга всегда недоступна по расписанию
        cmdParams.serviceId = QServiceTree.getInstance().getById(1540578931493L).getId();
        rpc20 = Executer.getInstance().aboutTask.process(cmdParams, "localhost", new byte[]{127, 0, 0, 1});
        assertNotNull(rpc20);
        assertTrue(rpc20 instanceof RpcGetServiceState);
        serviceState = (RpcGetServiceState) rpc20;
        assertEquals(serviceState.getResult().getLenghtLine(), 0);
        assertEquals(serviceState.getResult().getCode(), 1000000011);

        // услуга не назначена ни одному оператору
        cmdParams.serviceId = QServiceTree.getInstance().getById(1540579009027L).getId();
        rpc20 = Executer.getInstance().aboutTask.process(cmdParams, "localhost", new byte[]{127, 0, 0, 1});
        assertNotNull(rpc20);
        assertTrue(rpc20 instanceof RpcGetServiceState);
        serviceState = (RpcGetServiceState) rpc20;
        assertEquals(serviceState.getResult().getLenghtLine(), 0);
        assertEquals(serviceState.getResult().getCode(), 1000000000);
    }

    @Test
    public void testAboutNoWorkTime() {
        // у услуги нет рабочих часов никогла по расписанию. Есть ограничение по количесву в день. id=1604838685474
        // услгуга всегда недоступна по расписанию
        cmdParams.serviceId = QServiceTree.getInstance().getById(1604838685474L).getId();
        AJsonRPC20 rpc20 = Executer.getInstance().aboutTask.process(cmdParams, "localhost", new byte[]{127, 0, 0, 1});
        assertNotNull(rpc20);
        assertTrue(rpc20 instanceof RpcGetServiceState);
        RpcGetServiceState serviceState = (RpcGetServiceState) rpc20;
        assertEquals(serviceState.getResult().getLenghtLine(), 0);
        assertEquals(serviceState.getResult().getCode(), 1000000011);
    }

    @Test
    public void testAboutServicePersonLimit() {
        cmdParams.textData = "";
        cmdParams.serviceId = QServiceTree.getInstance().getRoot().getChildren().get(0).getId();
        AJsonRPC20 rpc20 = Executer.getInstance().aboutServicePersonLimit.process(cmdParams, "localhost", new byte[]{127, 0, 0, 1});
        assertNotNull(rpc20);
        assertTrue(rpc20 instanceof RpcGetInt);
        RpcGetInt getInt = (RpcGetInt) rpc20;
        assertEquals(getInt.getResult(), 0);


        QCustomer customer = new QCustomer(13);
        customer.setInputData("baned");
        ServerProps.getInstance().getProps().setBlackTime(100500);
        RpcBanList.getInstance().addToBanList(customer);
        cmdParams.textData = "baned";
        cmdParams.serviceId = QServiceTree.getInstance().getRoot().getChildren().get(0).getId();
        rpc20 = Executer.getInstance().aboutServicePersonLimit.process(cmdParams, "localhost", new byte[]{127, 0, 0, 1});
        assertNotNull(rpc20);
        assertTrue(rpc20 instanceof RpcGetInt);
        getInt = (RpcGetInt) rpc20;
        assertEquals(getInt.getResult(), 2);

        RpcBanList.getInstance().getBanList().forEach(RpcBanList.getInstance()::deleteFromBanList);
    }

    //1604842169856

    @Test
    public void testGetGridOfWeek() {
        // у услуги есть перерывы. id=1604842169856
        // услгуга всегда доступна по расписанию
        // 08:00 - 18:00 12-14 - все кроме выходных
        // 08:00 - 18:00 10-12 14-17 - субб
        // 09:00 - 17:00 10-12 14-17 - воскресенье
        cmdParams.serviceId = QServiceTree.getInstance().getById(1604842169856L).getId();
        Calendar now = Calendar.getInstance();
        int weekday = now.get(Calendar.DAY_OF_WEEK);
        int days = Calendar.SATURDAY - weekday + 2;
        now.add(Calendar.DAY_OF_YEAR, days);

        cmdParams.date = now.getTime().getTime();

        AJsonRPC20 rpc20 = Executer.getInstance().getGridOfWeek.process(cmdParams, "localhost", new byte[]{127, 0, 0, 1});
        assertNotNull(rpc20);
        assertTrue(rpc20 instanceof RpcGetGridOfWeek);
        RpcGetGridOfWeek gridOfWeek = (RpcGetGridOfWeek) rpc20;
        assertEquals(gridOfWeek.getResult().getAdvanceLimit(), 1);
        assertEquals(gridOfWeek.getResult().getAdvanceLimitPeriod(), 0);
        assertEquals(gridOfWeek.getResult().getAdvanceTimePeriod(), 60);
        assertNotNull(gridOfWeek.getResult().getStartTime());
        assertNotNull(gridOfWeek.getResult().getFinishTime());
        LinkedList<Date> times = gridOfWeek.getResult().getTimes();
        assertNotNull(times);
        assertTrue(times.size() != 0);
        assertEquals(times.size(), 41);
        for (Date time : times) {
            assertNotNull(time);
            assertTrue(time.after(new Date()));
        }

        now = Calendar.getInstance();
        weekday = now.get(Calendar.DAY_OF_WEEK);
        days = Calendar.SATURDAY + weekday - 2;
        now.add(Calendar.DAY_OF_YEAR, -days);

        cmdParams.date = now.getTime().getTime();

        rpc20 = Executer.getInstance().getGridOfWeek.process(cmdParams, "localhost", new byte[]{127, 0, 0, 1});
        assertNotNull(rpc20);
        assertTrue(rpc20 instanceof RpcGetGridOfWeek);
        gridOfWeek = (RpcGetGridOfWeek) rpc20;
        assertEquals(gridOfWeek.getResult().getAdvanceLimit(), 1);
        assertEquals(gridOfWeek.getResult().getAdvanceLimitPeriod(), 0);
        assertEquals(gridOfWeek.getResult().getAdvanceTimePeriod(), 60);
        assertNotNull(gridOfWeek.getResult().getStartTime());
        assertNotNull(gridOfWeek.getResult().getFinishTime());
        times = gridOfWeek.getResult().getTimes();
        assertNotNull(times);
        assertTrue(times.size() != 0);
        assertEquals(times.size(), 41);
        for (Date time : times) {
            assertNotNull(time);
            assertTrue(time.before(new Date()));
        }
    }
}